﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

using SharedGenomics.Domain;

namespace SharedGenomics.TextMining
{
    public class PublicationTitleMiner
    {
        #region Private Members

        private ScoredTermCollection _terms;
        private List<PublicationMining> _minedPublications;
        private bool _publicationListModifiedSinceLastSort;
        private StringTiler _tiler;

        #endregion

        #region Constructors

        public PublicationTitleMiner(ScoredTermCollection terms)
        {
            this.Terms = terms;

            this._minedPublications = new List<PublicationMining>();
            this._tiler = new StringTiler(this.Terms);
        }

        #endregion

        #region Public Methods

        public void MinePublication(Publication p)
        {
            if (p == null)
                throw new ArgumentNullException("p");

            //mine publication title for terms
            StringTiling tiles = this._tiler.Tile(p.Title);

            this.AddMinedPublication(p, tiles);
        }

        #endregion

        #region Private Methods

        private void AddMinedPublication(Publication p, StringTiling tiles)
        {
            Debug.Assert(p != null);
            Debug.Assert(tiles != null);

            this._minedPublications.Add(new PublicationMining(p, tiles));
            this._publicationListModifiedSinceLastSort = true;
        }

        private int CompareMinedPublications(PublicationMining m1, PublicationMining m2)
        {
            if (m1 == null)
            {
                //items are considered equal if both are null, otherwise m1 is smaller
                return (m2 == null) ? 0 : -1;
            }

            //m1 is not null
            //m1 is greater if m2 is null, otherwise compare using the score of the tiling of the two titles
            //note that since we want higher scoring titles at the start of the list we negate the result
            return (m2 == null) ? 1 : (-1 * (m1.TitleMining.CalculateScore().CompareTo(m2.TitleMining.CalculateScore())));
        }

        #endregion

        #region Properties

        public IEnumerable<PublicationMining> RankedMinedPublications
        {
            get
            {
                //sort list of mined publications by tiling score if required
                if (this._publicationListModifiedSinceLastSort)
                {
                    this._minedPublications.Sort(new Comparison<PublicationMining>(this.CompareMinedPublications));
                }

                return this._minedPublications;
            }
        }

        private ScoredTermCollection Terms
        {
            get { return this._terms; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("Terms");

                this._terms = value;
            }
        }

        #endregion
    }
}
